from paste.util import ip4

class GrantIPMiddleware(object):

    def __init__(self, app, ip_map, clobber_username = True):
        self.app = app
        self.ip_map = []
        for (key, value,) in ip_map.items():
            self.ip_map.append((ip4.IP4Range(key), self._convert_user_role(value[0], value[1])))

        self.clobber_username = clobber_username



    def _convert_user_role(self, username, roles):
        if (roles and isinstance(roles, basestring)):
            roles = roles.split(',')
        return (username, roles)



    def __call__(self, environ, start_response):
        addr = ip4.ip2int(environ['REMOTE_ADDR'], False)
        remove_user = False
        add_roles = []
        for (range, (username, roles,),) in self.ip_map:
            if (addr in range):
                if roles:
                    add_roles.extend(roles)
                if (username == '__remove__'):
                    remove_user = True
                else:
                    if username:
                        if ((not environ.get('REMOTE_USER')) or self.clobber_username):
                            environ['REMOTE_USER'] = username

        if (remove_user and ('REMOTE_USER' in environ)):
            del environ['REMOTE_USER']
        if roles:
            self._set_roles(environ, add_roles)
        return self.app(environ, start_response)



    def _set_roles(self, environ, roles):
        cur_roles = environ.get('REMOTE_USER_TOKENS', '').split(',')
        cur_roles = filter(None, cur_roles)
        remove_roles = []
        for role in roles:
            if role.startswith('-'):
                remove_roles.append(role[1:])
            else:
                if (role not in cur_roles):
                    cur_roles.append(role)

        for role in remove_roles:
            if (role in cur_roles):
                cur_roles.remove(role)

        environ['REMOTE_USER_TOKENS'] = ','.join(cur_roles)




def make_grantip(app, global_conf, clobber_username = False, **kw):
    from paste.deploy.converters import asbool
    clobber_username = asbool(clobber_username)
    ip_map = {}
    for (key, value,) in kw.items():
        if (':' in value):
            (username, role,) = value.split(':', 1)
        else:
            username = value
            role = ''
        if (username == '-'):
            username = ''
        if (role == '-'):
            role = ''
        ip_map[key] = value

    return GrantIPMiddleware(app, ip_map, clobber_username)



